package org.biloxi.model.magicobjects;

import java.util.Set;

import org.biloxi.commands.CommandRepository;
import org.biloxi.model.GameState;
import org.biloxi.model.player.PlayerState;
import org.biloxi.player.PlayerID;

/**
 * Represents an instance of a MTG Card.
 * MagicObjects are the building blocks of Biloxi as most of the rules  
 * of the game are contained in the cards. 
 * Encoding MTG Cards into Biloxi consists of the following:
 * 	1) Subclassing MagicObject or a subclass of MagicObject
 *  2) Programming the cards rules through:
 *  	a) attaching event listeners to react
 *  	b) modifying Game,Player,or MagicObject State through protected methods.
 * 
 * @author Peter.WM.Wong@gmail.com
 */
//TODO I think we should separate card state and logic.
//     Unfortunately we should assess how this will affect card development.
public abstract class MagicObject implements Cloneable {
	
	private boolean _faceup;
	private PlayerID _controller;
	private PlayerID _owner;
	private long _cardID;
	private String type;
	//TODO: add subtypes
	
	public boolean isFaceUp(){
		return _faceup;
	}
	
	// Made not-public so MagicObjectRegistry can only create MagicObjects
	protected MagicObject(CommandRepository cr, String type, long id){
		when = cr;
		_cardID = id;
		this.type = type;
	}
	
	//TODO Can we uniquely id cards through their name?
	//     Like "Wrath of God", there's only one those right?
	public abstract String getCardName();
	public abstract String getDescription();
	
	/**
	 * Called when MagicObject comes into play, regardless of from where (Hand, Library, etc.)
	 * Card Developers should subclass this method to attach {@link Command}   
	 */
	protected void comeIntoPlay(){}
	
	/* 
	 * Card Development API
	 * 
	 * The following protected methods allow Card Developers 
	 * to program the rules.  They methods fall under the category of
	 * 	 1) Querying  (State information)
	 *   2) Reacting  (Attaching/Detaching event listeners)
	 *   3) Modifying (Changing State)
	 */
	
	protected final CommandRepository when;

	/**
	 * Gets the GameState object.
	 * @return 
	 */
	final GameState getGameState(){
		return null; //TODO not implemented
	}
	
	/**
	 * Gets the PlayerState object of owner of this MagicObject.
	 * @return 
	 */
	final PlayerState getOwnerState(){
		return null; //TODO not implemented
	}
	
	final Set<PlayerState> getOpponentsStates(){
		return null; //TODO not implemented
	}

	/**
	 * Gets the id of owner of this MagicObject.
	 * 
	 * Owner of a MagicObject cannot change throughout the game, since biloxi doesn't play for ante
	 * 
	 * @return 
	 */
	public final PlayerID getOwnerID(){
		return _owner;
	}
	
	/**
	 * Gets the id of controller of this MagicObject.
	 * 
	 * Control of a MagicObject can change throughout the game.
	 * 
	 * @return 
	 */
	public final PlayerID getControllerID(){
		return _controller;
	}
	
	public final void setControllerID(PlayerID pid){
		_controller = pid;
	}
	
	
	//TODO: create enum of play zones and have card be contained in one, so may want getPlayZone(). Don't know if this will be useful besides for error checking.

	@Override
	protected Object clone() throws CloneNotSupportedException {
		//TODO not implemented
		return super.clone();
	}
	
	public final long getCardID(){
		return _cardID;
	}

	public final String getType() {
		return type;
	}

	public final void setType(String type) {
		this.type = type;
	}
}

